// ACPI nhcMethod Source Code
//
// NHC allows you to add one or more new ACPI methods to the operating system.
// With this powerful capacity of NHC you can add new or missing features to the operating system ACPI.
//
// Note: To test the nhcMethods please use the NHC ACPI Object Explorer.
// To use and call the nhcMethods please use the NHC ACPI Control System.
//
// Info: Please add the source code only inside a method. Source code outside a method will be ignored.
// To use acpi objects from the system acpi it is necessary to define it first with the External() keyword.
Method (SMCR, 2, NotSerialized) // Read data from the Apple System Management Controller (SMC)
{ // ===========================================================
// Arg0 = Apple SMC Key
// Arg1 = Data Length (1 to 4)
// ---------------------------
// Result0 = result status (0 = OK)
// Result1 = result value
// 0. Definition for the I/O Port access of the Apple SMC
//
OperationRegion(SMCF, SystemIO, 0x300, 0x01)
Field(SMCF, ByteAcc, NoLock, Preserve)
{
SMCD, 8, // Data Port used by Apple SMC
}
// 1. Definition of the result package
//
Name (RES_, Package (0x02)
{
0xFFFFFFFF, // result status (-1) -> 0 = OK
0x00 // result value
})
// 2. Send the read command to the SMC
//
Store(WCMD(0x10), Local0) // send read command (0x10) to the SMC
If(LEqual(Local0, 1)) // check status
{
Store (0xFFFFFFFE, Index (RES_, 0)) // set ERROR ID (-2)
Return (RES_) // ERROR -> send read command
}
// 3. Send the Apple SMC Key
//
Store(0, Local5) // init loop
While(LLess(Local5, 4)) // loop 4 times (0 to 3)
{
Multiply(Local5, 8, Local1) // actual shift amount (0, 8, 16, 24)
ShiftRight(Arg0, Local1, Local0) // get the actual byte to send
Store(Local0, SMCD) // send the key byte to the SMC Data Port
If(LEqual(WSTA(0x04), 1)) // wait until the SMC Command Port is ready
{
Store (0xFFFFFFFD, Index (RES_, 0)) // set ERROR ID (-3)
Return (RES_) // ERROR -> send the Key
}
Increment(Local5) // set to the next byte position
}
// 4. Send the data length to the SMC
//
Store(Arg1, SMCD) // send the data length to read to the SMC Data Port
// 5. Read the data from SMC
//
Store(0, Local1) // Init result
Store(0, Local5) // Init loop
While(LLess(Local5, Arg1)) // loop "data length" times
{
If(LEqual(WSTA(0x05), 1)) // wait until the SMC Command Port is ready
{
Store (0xFFFFFFFC, Index (RES_, 0)) // Set ERROR ID (-4)
Return (RES_) // ERROR -> send the Key
}
Store(SMCD, Local0) // receive data byte
Multiply(Local5, 8, Local6) // actual shift amount (0, 8, 16, 24)
ShiftLeft(Local0, Local6, Local0) // move the data byte to the right bit position in the result register
Or(Local0, Local1, Local1) // add data byte to the result register
Increment(Local5) // set to the next byte position
}
// 6. Return the package
//
Store (0, Index (RES_, 0)) // set OK status
Store (Local1, Index (RES_, 1)) // set result value
Return (RES_) // return result
}
Method (SMCW, 3, NotSerialized) // Write data to the Apple System Management Controller (SMC)
{ // ==========================================================
// Arg0 = Apple SMC Key
// Arg1 = Data to write
// Arg2 = Data Length (1 to 4)
// ---------------------------
// Result0 = result status (0 = OK)
// 0. Definition for the I/O Port access of the Apple SMC
//
OperationRegion(SMCF, SystemIO, 0x300, 0x01)
Field(SMCF, ByteAcc, NoLock, Preserve)
{
SMCD, 8, // Data Port used by Apple SMC
}
// 1. Send the write command to the SMC
//
Store(WCMD(0x11), Local0) // send write command (0x11) to the SMC
If(LEqual(Local0, 1)) // check status
{
Return (0xFFFFFFFE) // ERROR -> send write command (-2)
}
// 2. Send the Apple SMC Key
//
Store(0, Local5) // init loop
While(LLess(Local5, 4)) // loop 4 times
{
Multiply(Local5, 8, Local1) // actual shift amount (0, 8, 16, 24)
ShiftRight(Arg0, Local1, Local0) // get the actual byte to send
Store(Local0, SMCD) // send the key byte to the SMC Data Port
If(LEqual(WSTA(0x04), 1)) // wait until the SMC Command Port is ready
{
Return (0xFFFFFFFD) // ERROR -> send the Key (-3)
}
Increment(Local5) // set to the next byte position
}
// 3. Send the data length to the SMC
//
Store(Arg2, SMCD) // send the data length to write to the SMC Data Port
// 4. Write the data to the SMC
//
Store(0, Local1) // init result
Store(0, Local5) // init loop
While(LLess(Local5, Arg2)) // loop "data length" times
{
If(LEqual(WSTA(0x04), 1)) // wait until the SMC Command Port is ready
{
Return (0xFFFFFFFC) // ERROR - Read Data (-4)
}
Multiply(Local5, 8, Local6) // actual shift amount (0, 8, 16, 24)
ShiftRight(Arg1, Local6, Local0) // extract the data byte with the right bit position from Arg1
Store(Local0, SMCD) // send data byte
Increment(Local5) // set to the next byte position
}
Return (0) // Return Status OK (write success)
}
Method (WCMD, 1, NotSerialized) // Send command to the SMC and wait for the ready status
{ // =====================================================
// Arg0 = Command to send
// Definition for the I/O Port access of the Apple SMC
//
OperationRegion(SMCF, SystemIO, 0x304, 0x01)
Field(SMCF, ByteAcc, NoLock, Preserve)
{
SMCC, 8 // Command/Status Port used by Apple SMC
}
// Special treatment of command port - on newer macbooks, it seems necessary
// to resend the command byte before polling the status again.
//
Store(0x40, Local5) // start/minimum wait time = 64us (APPLESMC_MIN_WAIT = 0x40)
While(LLess(Local5, 0x8000)) // wait up to 32ms for the status port (APPLESMC_MAX_WAIT = 0x8000)
{
Store(Arg0, SMCC) // send/resend read command to the SMC
WSMC(Local5) // wait (64us or more)
Store(SMCC, Local0) // read SMC command port status
And(Local0, 0x0F, Local0) // mask port status value
If(LEqual(Local0, 0x0C)) // check SMC command port status
{
Return (0) // status received (masked with 0x0f) - terminate loop
}
Else
{
ShiftLeft(Local5, 1, Local5) // increment wait time
}
}
Return (1) // ERROR - TIME OUT
}
Method (WSTA, 1, NotSerialized) // Wait Status - wait for the status port to get a certain value
{ // =============================================================
// Arg0 = Status
// Definition for the I/O Port access of the Apple SMC
//
OperationRegion(SMCF, SystemIO, 0x304, 0x01)
Field(SMCF, ByteAcc, NoLock, Preserve)
{
SMCC, 8 // Command/Status Port used by Apple SMC
}
// Wait up to 32ms for the status port to get a certain value
// (masked with 0x0f), returning zero if the value is obtained.
//
And(Arg0, 0x0F, Arg0) // mask value
Store(0x40, Local5) // start/minimum wait time = 64us (APPLESMC_MIN_WAIT = 0x40)
While(LLess(Local5, 0x8000))
{
WSMC(Local5) // wait (64us or more)
Store(SMCC, Local0) // read SMC command port status
And(Local0, 0x0F, Local0) // mask port status value
If(LEqual(Local0, Arg0)) // check SMC command port status
{
Return (0) // status received (masked with 0x0f) - terminate loop
}
Else
{
ShiftLeft(Local5, 1, Local5) // increment wait time
}
}
Return (1) // ERROR - TIME OUT
}
Method (WSMC, 1, NotSerialized) // Wait for SMC - delay method for the SMC access
{ // ================================================
// Arg0 = delay time in microseconds
// For very short delays (1 to 100 microseconds) we must use Stall.
// The resolution of sleep is not accurate enought. For delays longer than 100 microseconds we must use Sleep.
//
If(LLessEqual(Arg0, 100))
{
Stall(Arg0) // usec delay
}
Else
{
Divide(Arg0, 100, Local1, Local0) // split the delay time
While(LGreater(Local0, 0))
{
Stall(100) // usec delay
Decrement(Local0)
}
Stall(Local1) // consider also the remainder of the division
}
}
Method (SR16, 1, NotSerialized) // Read text from the Apple System Management Controller (SMC)
{ // ===========================================================
// Arg0 = Apple SMC Key
// ---------------------------
// Result0 = result status (0 = OK)
// Result1 - Result4 = text (char[16])
// 0. Definition for the I/O Port access of the Apple SMC
//
OperationRegion(SMCF, SystemIO, 0x300, 0x01)
Field(SMCF, ByteAcc, NoLock, Preserve)
{
SMCD, 8, // Data Port used by Apple SMC
}
// 1. Definition of the result package
//
Name (RES_, Package (0x5)
{
0xFFFFFFFF, // result status (-1) -> 0 = OK
0x00000000, // result byte 1-4
0x00000000, // result byte 5-8
0x00000000, // result byte 9-12
0x00000000, // result byte 13-16
})
// 2. Send the read command to the SMC
//
Store(WCMD(0x10), Local0) // send read command (0x10) to the SMC
If(LEqual(Local0, 1)) // check status
{
Store (0xFFFFFFFE, Index (RES_, 0)) // set ERROR ID (-2)
Return (RES_) // ERROR -> send read command
}
// 3. Send the Apple SMC Key
//
Store(0, Local5) // init loop
While(LLess(Local5, 4)) // loop 4 times
{
Multiply(Local5, 8, Local1) // actual shift amount (0, 8, 16, 24)
ShiftRight(Arg0, Local1, Local0) // get the actual byte to send
Store(Local0, SMCD) // send the key byte to the SMC Data Port
If(LEqual(WSTA(0x04), 1)) // wait until the SMC Command Port is ready
{
Store (0xFFFFFFFD, Index (RES_, 0)) // set ERROR ID (-3)
Return (RES_) // ERROR -> send the Key
}
Increment(Local5) // set to the next byte position
}
// 4. Send the data length to the SMC
//
Store(16, SMCD) // send the data length to read to the SMC Data Port
// 5. Fill the package with data
//
Store(0, Local7) // Init the package Index
While(LLess(Local7, 4)) // Loop 4 times (0 to 3)
{
// 6. Read the data from SMC
//
Store(0, Local1) // Init result
Store(0, Local5) // Init 4 times loop
While(LLess(Local5, 4)) // loop 4 times (0 to 3)
{
If(LEqual(WSTA(0x05), 1)) // wait until the SMC Command Port is ready
{
Store (0xFFFFFFFC, Index (RES_, 0)) // Set ERROR ID (-4)
Return (RES_) // ERROR -> send the Key
}
Store(SMCD, Local0) // receive data byte
Multiply(Local5, 8, Local6) // actual shift amount (0, 8, 16, 24)
ShiftLeft(Local0, Local6, Local0) // move the data byte to the right bit position in the result register
Or(Local0,Local1,Local1) // add data byte to the result register
//
Increment(Local5) // set to the next byte position
}
// 7. Store received data in the package
//
Increment(Local7) // Set to the next position in the package
Store (Local1, Index (RES_, Local7)) // Set result value in the package
}
// 8. Return the package
//
Store (0, Index (RES_, 0)) // set OK status
Return (RES_) // return result
}